package org.springframework;

import java.net.BindException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.connector.ClientAbortException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.zjdiepu.www.common.consts.SystemConsts;
import com.zjdiepu.www.config.ServerConfig;
import com.zjdiepu.www.response.BaseResponse;
import com.zjdiepu.www.response.BooleanResponse;
import com.zjdiepu.www.security.base.enums.ResultCode;
import com.zjdiepu.www.security.exception.BasePartnerException;
import com.zjdiepu.www.security.server.core.Partners;
import com.zjdiepu.www.security.server.encode.ServerEncryptAndDencryptUtil;
import com.zjdiepu.www.security.server.interceptor.PartnerHolder;
import com.zjdiepu.www.security.server.sign.ServerSignFactory;
import com.zjdiepu.www.security.sign.ISign;
import com.zjdiepu.www.security.sign.rsa.RsaSign;
/**
 * 类描述: 全局异常处理 <br/>     
 * 项目名称:diepu-parent-xinhehui <br/> 
 * 类名称:MyHandlerExceptionResolver <br/>     
 * 创建人:xiongxiaotun <br/> 
 * 创建时间:2017年8月15日 下午4:35:30  <br/>   
 * 修改人:xiongxiaotun <br/> 
 * 修改时间: 2017年8月15日 下午4:35:30   <br/>  
 * 修改备注:   <br/> 
 * @version V1.0   <br/>
 */
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
	private static final Logger logger = LoggerFactory.getLogger(MyHandlerExceptionResolver.class);
	
	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
		if (ex == null) {
			return null;
		}
		
		boolean log = true;
		String requestURI = request.getRequestURI();
		String mobileFlag = request.getHeader(SystemConsts.MOBILE_FLAG);
		if(ex instanceof ClientAbortException){ //请求主动断开（比如刷新页面等导致打断请求）
			log = false;
		} else if(ex instanceof BasePartnerException) {
			BasePartnerException bex = (BasePartnerException)ex;
			logger.error("请求发生异常.requestURI:{}.第三方调用异常,异常编码：{}，异常信息：{}, 客户端:{}，异常栈：{}.", requestURI, bex.getErrorCode(), bex.getErrorMsg(), mobileFlag, ex);
			log = false;
		}
		
		if(log) {
			String contextPath = request.getContextPath();
			if(!requestURI.equals(contextPath + "/user/login")){ //登录POST
				logger.error("请求发生异常.requestURI:{}, 客户端:{}..异常栈:{}", requestURI, mobileFlag, ex);
			}
		}
		
		BaseResponse<BooleanResponse> responseFail = null;
		if (ex instanceof MethodArgumentNotValidException) {
			responseFail = BaseResponse.create(ResultCode.FAIL_PARAM_VALIDATE);
		} else if (ex instanceof BindException) {
			responseFail = BaseResponse.failWithBoolean(ResultCode.FAIL_PARAM_VALIDATE);
		} else if (ex instanceof BasePartnerException) {
			BasePartnerException e = (BasePartnerException)ex;
			responseFail = BaseResponse.failWithBoolean(e.getErrorCode(), e.getErrorMsg());
		} else if (ex instanceof HttpRequestMethodNotSupportedException) {
			responseFail = BaseResponse.failWithBoolean(ResultCode.HTTP_METHOD_ERROR);
		}
		if(null == responseFail) {
			responseFail = BaseResponse.failWithBoolean(ResultCode.EXCEPTION_UNKNOW);
		}
		ModelAndView mv = new ModelAndView(new MyJsonView());
		
		boolean partnerSignResponseSwitch = false;
		Partners partner = PartnerHolder.getPartner();
		if(null != partner) {
			partnerSignResponseSwitch = ServerConfig.getPartnerSignResponseSwitch(partner);
		}
		if(partnerSignResponseSwitch) {
			BooleanResponse content = responseFail.getContent();
			content.setTimestamp(System.currentTimeMillis());
			ISign sign = ServerSignFactory.getSign(partner);
        	boolean isRsaResp = false;
     		if(sign instanceof RsaSign) {
     			isRsaResp = true;
     		}
			String signSecretKey = ServerConfig.getPartnerSignSecretKey(partner);
			String saltOrSecretKey = ServerSignFactory.getSignSaltOrSecretKey(partner);
			String signName = ServerConfig.getPartnerSignName(partner);
			String signCovenantKeyName = ServerConfig.getPartnerSignCovenantKeyName(partner);
			content.setSign(sign.generateSign(content, signSecretKey, saltOrSecretKey, signName, signCovenantKeyName, isRsaResp));
			String responseData = JSON.toJSONString(responseFail);
			mv.addObject(SystemConsts.ERROR_OBJECT, ServerEncryptAndDencryptUtil.encrypt(responseData, partner));
		} else {
			mv.addObject(SystemConsts.ERROR_OBJECT, responseFail);
		}
		return mv;
	}

}
